function [rate_funcs,string_form] = getRates_powerLaw_v3_0(key)
%% getRates_powerLaw_v2_0
%  Version 2.0
%  Author: Adeyinka Lesi
%  Date: 7/20/17
%  Project: Tumor Growth, Logarithmic Continuum Form
% getRateFunctions_v1_0 uses rate parameters to create functions for
% the growth, death, shedding and metastasis of tumors. This version assume
% growth is described as k*j^i
% params: struct; rate parameters
% rate_funcs: struct; contains rate functions
% string_form: string; the formula for parameters is stated explicitly
%% VERSION HISTORY
%  1.1: This version produces a string with the parameters expressed as
%  equations (used to label plots)
%  1.2: Changed string format, added second deriv
%  2.0: implementing carrying capacity (by modifying string_form)
%  3.0: passing key in in case death_starter or death_ramp is used

params = key.PARAMETERS;
rate_funcs = struct();
rate_funcs.growth = @(x) params.growth1*x.^params.growth2;
rate_funcs.shed = @(x) params.shed1*x.^params.meta2;
rate_funcs.meta = @(x) params.meta1*x.^params.meta2;
uncut_func = @(x) params.death1*x.^params.death2;
if(params.death_cutoff_present)
    rate_funcs.death = @(x) uncut_func(x).*(x<params.death_cutoff);
else
    rate_funcs.death = uncut_func;
end
% first derivative
rate_funcs.growth_deriv = @(x) params.growth2*params.growth1*x.^(params.growth2-1);
rate_funcs.shed_deriv = @(x) params.meta2*params.shed1*x.^(params.meta2-1);
rate_funcs.meta_deriv = @(x) params.meta2*params.meta1*x.^(params.meta2-1);
uncut_func2 = @(x) params.death2*params.death1*x.^(params.death2-1);
if(params.death_cutoff_present)
    rate_funcs.death_deriv = @(x) uncut_func2(x).*(x<params.death_cutoff);
else
    rate_funcs.death_deriv = uncut_func2;
end
% second derivative
rate_funcs.growth_2deriv = @(x) params.growth2*(params.growth2-1)*params.growth1*x.^(params.growth2-2);
rate_funcs.shed_2deriv = @(x) params.meta2*(params.meta2-1)*params.shed1*x.^(params.meta2-2);
rate_funcs.meta_2deriv = @(x) params.meta2*(params.meta2-1)*params.meta1*x.^(params.meta2-2);
uncut_func3 = @(x) params.death2*(params.death2-1)*params.death1*x.^(params.death2-2);
if(params.death_cutoff_present)
    rate_funcs.death_2deriv = @(x) uncut_func3(x).*(x<params.death_cutoff);
else
    rate_funcs.death_2deriv = uncut_func3;
end

% string containing the form of the equations
if(params.death_cutoff_present)
    if(isfield(key,'USING_DEATH_STARTER') && key.USING_DEATH_STARTER)
        format = ['k_g=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_r=%1.2e\\cdot{}x^{%1.2f} (x<' ...
            num2str(params.death_cutoff) ', t>' ...
            num2str(key.DEATH_START_TIME) '), ' ...
            'k_s=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_m=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'cc=%1.2e'];
    elseif(isfield(key,'USING_DEATH_RAMP') && key.USING_DEATH_RAMP)
        ramp_start = key.DEATH_RAMP_CENTER-0.5*key.DEATH_RAMP_WIDTH;
        ramp_end = key.DEATH_RAMP_CENTER+0.5*key.DEATH_RAMP_WIDTH;
        ramp_start = round(10*ramp_start)*0.1;
        ramp_end = round(10*ramp_end)*0.1;
        format = ['k_g=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_r=%1.2e\\cdot{}x^{%1.2f} (x<' ...
            num2str(params.death_cutoff) ',ramp(' ...
            num2str(ramp_start) '->' num2str(ramp_end) ')), '...
            'k_s=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_m=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'cc=%1.2e'];
    else
        format = ['k_g=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_r=%1.2e\\cdot{}x^{%1.2f} (x<' ...
            num2str(params.death_cutoff) '), ' ...
            'k_s=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_m=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'cc=%1.2e'];
    end
else
    if(isfield(key,'USING_DEATH_STARTER') && key.USING_DEATH_STARTER)
        format = ['k_g=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_r=%1.2e\\cdot{}x^{%1.2f} (t>' ...
            num2str(key.DEATH_START_TIME) '), ' ...
            'k_s=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_m=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'cc=%1.2e'];
    elseif(isfield(key,'USING_DEATH_RAMP') && key.USING_DEATH_RAMP)
        ramp_start = key.DEATH_RAMP_CENTER-0.5*key.DEATH_RAMP_WIDTH;
        ramp_end = key.DEATH_RAMP_CENTER+0.5*key.DEATH_RAMP_WIDTH;
        ramp_start = round(10*ramp_start)*0.1;
        ramp_end = round(10*ramp_end)*0.1;
        format = ['k_g=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_r=%1.2e\\cdot{}x^{%1.2f} (ramp(' ...
            num2str(ramp_start) '->' num2str(ramp_end) ')), '...
            'k_s=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_m=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'cc=%1.2e'];
    else
        format = ['k_g=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_r=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_s=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'k_m=%1.2e\\cdot{}x^{%1.2f}, ' ...
            'cc=%1.2e'];
    end
end

string_form = sprintf(format,[params.growth1, params.growth2, ...
                              params.death1, params.death2, ...
                              params.shed1, params.meta2, ...
                              params.meta1, params.meta2, ...
                              params.carrying_capacity]);

